通常只有在產品功能比較簡單的情況下才會在元件內進行遠端資料的請求,因為功能複雜的產品,往往請求的 API 也比較多且複雜,若在元件內處理,會讓元件顯得很混亂,難以維護,但這邊我們還是簡單示範一下元件內請求資料的方式。
在 class component 請求資料,通常是在 componentDidMount 中執行,如下面的範例
class UserProfile extends React.Component {
state = {
data: []
}
componentDidMount () {
// ajax、fetch、axios 請求遠端資料
if (data) {
this.setState({data: data})
}
}
render() {
const { data } = this.state
return (
<div>
{ data }
</div>
);
}
}
前面的文章有提過,function component 是沒有生命週期的,但是它可以借助 react hook 中的 useEffect 函式來處理資料請求,有關 react hook 詳細的部分,會在後面的文章在做整理。useEffect 相當於 class component 中的 componentDidMount,他接受兩個參數,第一個參數是函式,可以在裡面做非同步行為,像是資料請求,然後再更新資料。下面的範例中我們還有使用到 useState 這個方法,也是 react hook 的一個函式,基本上是調用這個函式來做資料管理,這部分會在後面的文章中再做詳細整理,這邊只是一個簡易範例。
import React, { useEffect, useState } from 'react';
const UserProfile = () => {
const [data, setData] = useState(null)
useEffect(async () => {
// ajax、fetch、axios 請求遠端資料
if (result) {
setData(result.data)
}
})
return <div>
{ data }
</div>
}
元件外部的資料請求,指的通常是在元件外部請求資料後,由第三方套件做資料管理。通常產品開發上資料很複雜時,都會使用第三方套件來做資料管理,比方說 redux、mobx、dva,它們都有很好的資料管理功能。課程中是以 dva 為例,dva 提供了一個 model 模組做資料管理,下面是一個簡單的範例,大概呈現 dva 是如何管理資料。
const fetchUserData = () => {
return fetch('/api/userData').then(res => res.json())
}
model 層處理和更新資料。namespace 是 model 的名字,model 內也有 state 屬性,但是這是 dva 本身的 state(元件外部的 state),和 React 元件中的 state 不是同一個。effects 是處理副作用的,遠端資料請求就是在這邊處理,會叫副作用是因為這讓我們的函式變得比較不純。另外,需要注意在 effects 中是使用 generator 來處理同步和非同步,async await 是不能用的。我們利用 call 去調用前面的 fetchUserData 來取得遠端資料,在用 put 去更新,put 中的參數,type 是去指定使用的函式,在這邊是使用 reducers 裡面的 updateUserData ,payload 是傳送到函式的參數。reducers 中會得到舊的資料狀態(state)和更新的資料狀態(action.payload),整合後返回一個新的 state。app.model({
namespace: 'userData',
state: {
userData: []
},
effects: {
//generator 處理非同步
*getUserData(action, {call, put}) {
const user = yield call(fetchUserData, 1000)
yield put({type: 'updateUserData', payload: { user }})
}
},
reducers: {
updateUserData( state, action) {
return {...state, ...action.payload}
}
},
subscriptions: {
//訂閱
}
})
state 同步更新到 React 元件中,要使用 dva 提供的一個函式 connect,這個函式可以將 dva 中的資料和元件連結。如下面的程式碼,UserProfile 是我們在 React 中自訂的元件,透過 connect 去取得資料,並返回一個全新的元件。import { connect } from 'dva'
connect((state) => {
return { user: state.user }
})(UserProfile)
componentDidMount 裡面利用 dispatch 去調用 dva model 的 effects 中的函式,這樣就會取得資料並更新資料,並完成元件的更新。class UserProfile extends React.Component {
componentDidMount () {
this.props.dispatch({ type: getUserData})
}
render() {
const { userData } = this.props
return (
<div>
{ userData }
</div>
);
}
}
基本上只要專案有一定規模,通常還是會採用第三方套件去管理遠端請求回來的資料,不只是開發上比較方便,維護性也比較高。另外,通常 API 複雜的產品,其實也會統一 API 的管理,這部份我們會在下一篇提到。